""" 复用基本工具静态方法模块"""
import datetime
import functools
import json
import logging
import os
import subprocess
import sys
import xml.etree.ElementTree as ElementTree

import pandas
import requests
from requests.adapters import HTTPAdapter
from xToolkit import xfile

from code_metric.config import init_global_config_setting

CONFIG = init_global_config_setting()
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
date_start_run = ''
host_com_dict = {}


def get_date(static_while_running=True):
    if not static_while_running:
        return datetime.datetime.now().strftime('%Y-%m-%d')
    global date_start_run
    if not date_start_run:
        date_start_run = datetime.datetime.now().strftime('%Y-%m-%d')
    return date_start_run


def make_sure_dir_exist(directory):
    if not os.path.exists(directory):
        os.makedirs(directory, mode=0o777, exist_ok=False)


def write_as_excel(output_file_name, source_info_dict_list, columns_order,
                   columns_rename_map=None, columns_in_percent=None, sheet_name='Sheet1', writer_for_sharding=None):
    """
    生成excel表
    :param output_file_name: 输出文件名
    :param source_info_dict_list: 待写入数据的字典列表
    :param columns_order: 列名顺序
    :param columns_rename_map: 需要重命名的列名字典
    :param columns_in_percent: 需要转换为百分数的列
    :param sheet_name: 表单名字
    :param writer_for_sharding: 对过长的数据，进行递归分表
    """
    if not source_info_dict_list:
        print('所传入信息列表没有任何内容，故而无表生成。')
        return 0

    if writer_for_sharding is None:
        writer = pandas.ExcelWriter(output_file_name, engine='xlsxwriter',
                                    engine_kwargs={'options': {'strings_to_urls': False}})
    else:
        writer = writer_for_sharding

    if len(source_info_dict_list) > 1_000_000:
        print('所传入信息列表过长，故而将分表生成结果。')
        sharding_source_info_dict_list = source_info_dict_list[1_000_000:]
        sharding_sheet_name = sheet_name + '_' + str(len(sharding_source_info_dict_list))
        info_dict_list_to_write = source_info_dict_list[:1_000_000]
    else:
        info_dict_list_to_write = source_info_dict_list
    pf = pandas.DataFrame(info_dict_list_to_write)
    pf = pf[columns_order]
    alphabet_columns_in_percent = []
    if columns_in_percent:
        for column in columns_in_percent:
            alphabet_columns_in_percent.append(chr(65 + columns_order.index(column)))
    if columns_rename_map:
        pf.rename(columns=columns_rename_map, inplace=True)
    pf.fillna(' ', inplace=True)
    pf.to_excel(writer, encoding='utf-8', index=False, sheet_name=sheet_name)
    if columns_in_percent:
        format_obj = writer.book.add_format({'num_format': '0.00%'})
        for alphabet in alphabet_columns_in_percent:
            writer.book.sheetnames['Sheet1'].set_column(f'{alphabet}:{alphabet}', cell_format=format_obj)
    if len(source_info_dict_list) > 1_000_000:
        write_as_excel(output_file_name, sharding_source_info_dict_list, columns_order, columns_rename_map,
                       columns_in_percent, sharding_sheet_name, writer)
    if writer_for_sharding is None:
        writer.save()
    return len(info_dict_list_to_write)


def read_excel_to_dict_list(file):
    content = xfile.read(file).excel_to_dict(max=float('inf'))
    if not isinstance(content, list):
        logging.warning(f'所读取的文件{file}不存在，即将返回空列表')
        content = []
    return content


def request_get(url, max_retries=2, timeout=3):
    # 设置重连次数
    session = requests.session()
    session.mount('http://', HTTPAdapter(max_retries=max_retries))
    session.mount('https://', HTTPAdapter(max_retries=max_retries))
    # 设置连接活跃状态为False
    session.keep_alive = False
    response = session.get(url=url, timeout=timeout)
    return response


def is_token_valid(access_token):
    test_url = f'https://gitee.com/api/v5/orgs/openharmony/repos?access_token={access_token}'
    response_code = request_get(test_url).status_code
    return response_code != 401


def is_organization_valid(org_name):
    access_token = CONFIG['access_token']
    url_to_test = f'https://gitee.com/api/v5/orgs/{org_name}?access_token={access_token}'
    response_code = request_get(url_to_test).status_code
    if response_code == 401:
        print('access_token已失效，无法进行有效判定。')
        return False
    return response_code != 404


def is_repo_valid(owner_name, repo_name):
    access_token = CONFIG['access_token']
    url_to_test = f'https://gitee.com/api/v5/repos/{owner_name}/{repo_name}/labels?access_token={access_token}'
    response_code = request_get(url_to_test).status_code
    if response_code == 401:
        print('access_token已失效，无法进行有效判定。')
        return False
    return response_code != 404


def get_json_response_from_url(request_url):
    response = request_get(request_url, timeout=100)
    json_obj_list = json.loads(response.text)
    if 'message' in json_obj_list:
        logging.error('访问url出错：' + request_url)
        logging.error('错误信息如下：' + json_obj_list['message'])
    if type(json_obj_list) == list and len(json_obj_list) > 0:
        return json_obj_list
    return []


def get_json_response_list_from_url_list(url_list):
    response_list = []
    for request_url in url_list:
        json_response = get_json_response_from_url(request_url)
        if not json_response:
            break
        response_list.extend(json_response)
    return response_list


def get_xml_response_from_url(request_url):
    response = request_get(request_url)
    root = ElementTree.fromstring(response.text)
    return root


def run_command_with_feedback(cmd, **kwargs):
    logging.info('cmd=' + str(cmd))
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, **kwargs)
    log_file = os.path.join(BASE_DIR, 'stats.log')
    with open(log_file, 'a', encoding="utf-8") as f:
        output = sys.stdout if CONFIG['environment'] == 'dev' else f
        for line in iter(process.stdout.readline, ''):
            output.write(line)
            output.flush()
    process.wait()
    return process.returncode


def run_command_write_result(cmd, cwd, output, **kwargs):
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, errors='ignore', **kwargs)
    last_line = ''
    with open(output, 'w', encoding='utf-8') as f:
        for line in iter(process.stdout.readline, ''):
            f.write(line)
            last_line = line
    process.wait()
    return last_line


def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance


def retry(max_retry_times=3, retry_on_result=False):
    def decorator(func):
        def wrapper(*args, **kw):
            is_it_work = func(*args, **kw)
            retry_times_left = max_retry_times
            while is_it_work == retry_on_result and retry_times_left > 0:
                is_it_work = func(*args, **kw)
                retry_times_left -= 1

        return wrapper

    return decorator


def clock(func):
    @functools.wraps(func)
    def clocked(*args, not_clock_me=False, **kwargs):
        start = datetime.datetime.now()
        result = func(*args, **kwargs)
        end = datetime.datetime.now()
        duration = (end - start).seconds
        stop_at = end.strftime('%Y-%m-%d %X')
        if not not_clock_me:
            formed_dur = str(datetime.timedelta(seconds=duration))
            print(f"时间记录：于{stop_at}执行完毕，耗时{formed_dur}\n")
        return result

    return clocked


def get_email_host_to_com_dict():
    global host_com_dict
    if not host_com_dict:
        host_com_config_file = os.path.join(BASE_DIR, CONFIG['tool_path'], CONFIG['host_com_file'])
        for company_info in read_excel_to_dict_list(host_com_config_file):
            host_com_dict[company_info['邮箱后缀']] = company_info['企业名称company_short']
    return host_com_dict


if __name__ == '__main__':
    pass
